# coding=utf8
#    Tichy
#
#    copyright 2008 Guillaume Chereau (charlie137@gmail.com)
#
#    This file is part of Tichy.
#
#    Tichy is free software: you can redistribute it and/or modify it
#    under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    Tichy is distributed in the hope that it will be useful, but
#    WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#    General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with Tichy.  If not, see <http://www.gnu.org/licenses/>.

"""contact module"""

__docformat__ = 'reStructuredText'

import logging
LOGGER = logging.getLogger('Contact')

import tichy
import tichy.gui as gui
from struct import Struct
from attribute import Attribute


class Contact(Struct):
    """base class for tichy's contacts
    """

    storage = None

    name = Attribute('name', tichy.Str)
    tel = Attribute('tel', tichy.TelNumber)
    fields = [name, tel]

    def __init__(self, name="", tel="", **kargs):
        super(Contact, self).__init__()
        self.name = name
        self.tel = tel

    @property
    def title(self):
        return self.name

    @property
    def id(self):
        return self.name

    @property
    def subtitle(self):
        """Return an optional sub text for the item"""
        return self.tel

    def create_actor(self):
        """Return an actor acting on this contact

        :Returns: `tichy.Actor`
        """
        actor = super(Contact, self).create_actor()
        actor.new_action("Call").connect('activated', self._on_call)
        # actor.new_action("Delete").connect('activated', self._on_delete)

        for cls in Contact.subclasses:
            if isinstance(self, cls):
                continue
            import_ = actor.new_action("Copy to %s" % cls.storage)
            import_.connect('activated', self._on_copy_to, cls)

        return actor

    def _on_copy_to(self, action, contact, cls):
        try:
            contact = yield cls.import_(self)
            tichy.ContactsService.get().add(contact)
        except Exception, ex:
            LOGGER.error("can't import contact : %s", ex)
            yield tichy.Dialog(None, "Error",
                               "can't import the contact")

    def _on_call(self, _action, contact):
        caller = tichy.phone.CallerService.get()
        yield caller.call(None, contact.tel)


class PhoneContact(Contact):
    """Contact that is stored on the phone"""

    storage = 'Phone'

    def __init__(self, **kargs):
        super(PhoneContact, self).__init__(**kargs)

    @classmethod
    def import_(cls, contact):
        """import a contact into the phone"""
        assert not isinstance(contact, PhoneContact)
        yield PhoneContact(name=contact.name, tel=contact.tel)


class ContactsService(tichy.Service):
    """Allow to add and get the phone or sim contacts"""

    def __init__(self):
        super(ContactsService, self).__init__()
        self.contacts = tichy.List()
        self.database = tichy.Persistance(PhoneContact, 'contacts')

    @tichy.tasklet.tasklet
    def init(self):
        LOGGER.info("load contacts from phone")
        contacts = self.database.load_all()
        LOGGER.info("got %d contacts", len(contacts))
        for contact in contacts:
            self.add(contact)

        LOGGER.info("load contacts from SIM")
        contacts = yield tichy.phone.SIMService.get().get_contacts()
        LOGGER.info("got %d contacts", len(contacts))
        for contact in contacts:
            self.add(contact)

        yield None

    @tichy.tasklet.tasklet
    def copy_all(self):
        """copy all the contacts into the phone"""
        to_add = []
        for contact in self.contacts:
            if isinstance(contact, PhoneContact):
                continue
            if any([isinstance(c, PhoneContact) for c in \
                        self.find_by_number(contact.tel)]):
                continue
            contact = yield PhoneContact.import_(contact)
            to_add.append(contact)
        self.contacts.extend(to_add)

    def add(self, contact):
        """Add a contact into the contact list"""
        self.contacts.append(contact)
        if isinstance(contact, PhoneContact):
            self.database.add(contact)

#     def remove(self, contact):
#         """Remove a contact from the contact list"""
#         self.contacts.remove(contact)

    def find_by_number(self, number):
        """Return all the contacts having a given number

        :Parameters:
            number : str
               The number of the contact

        :Returns: list of `Contact`
        """
        return [x for x in self.contacts if x.tel == number]

    def find_by_name(self, name):
        for contact in self.contacts:
            if contact.name == name:
                return contact
        else:
            raise KeyError("no contact named '%s'" % name)


class SelectContactService(tichy.Service):

    def select(self, window):
        raise NotImplementedError
